/* ****************************************************************************
 *
 * Copyright (c) Microsoft Corporation. 
 *
 * This source code is subject to terms and conditions of the Microsoft Public License. A 
 * copy of the license can be found in the License.html file at the root of this distribution. If 
 * you cannot locate the  Microsoft Public License, please send an email to 
 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Public License.
 *
 * You must not remove this notice, or any other, from this software.
 *
 * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
 * PARTICULAR PURPOSE.
 * ***************************************************************************/




#if !defined(AFX_LINEGL_H__4DACBB76_9EFC_11D4_8A95_D4B14EEC3D7F__INCLUDED_)
#define AFX_LINEGL_H__4DACBB76_9EFC_11D4_8A95_D4B14EEC3D7F__INCLUDED_

#include <pgl/core/PGLObject.h>
#include <pgl/core/PGLMarker.h>

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

/*! \defgroup PGLLineGroup Lines and curves
\ingroup PGLObjectGroup
*/

/*! \brief A generic line class. 

\ingroup PGLLineGroup
This is the base class for 2D and 3D curves. It holds all the carateristics of these lines :
<ul>
	<li><b>Point type:</b> There are 1 different shapes of points :
	The corresponding constants are 
	<ul>
		<li> #MarkerTypeNone : no point
		<li> #MarkerTypeCircle : circle
		<li> #MarkerTypeContour : a circle
		<li> #MarkerTypeTriangle : a triangle
		<li> #MarkerTypeSquare : a square
	</ul>
	<li><b>Point width:</b> the point width in pixels
	<li><b>Line type:</b> Dashing patterns.
	The corresponding constants are 
	<ul>
		<li> #PGL_LINE_CONT : -------
		<li> #PGL_LINE_BARBAR : - - - -
		<li> #PGL_LINE_BARPOINT : -.-.-.
	</ul>
	But you can also set your own custom dashing pattern.
	The elements in the string array set the length of each dash and space in the dash pattern. 
	The first element sets the length of a dash, the second element sets the length of a space, the third element sets the length of a dash, and so forth.
	<li><b>Line width:</b> the line width in pixels
	<li><b>Interpolation type:</b> There are 4 different interpolation methods : piece wize linear or splines
	The corresponding enumeration is EInterpolationType 
	<ul>
		<li> #InterpolationTypeStep : steps (zero order interpolation)
		<li> #InterpolationTypeLinear : piecewize linear interpolation
		<li> #InterpolationTypeSpline : cardinal spline with tension
		<li> #InterpolationTypeSegment : multiple line strip
	</ul>	
	<li>Open or closed curve,</li>
	<li>Filling: See brushes section,</li>
	<li>Contouring: disable contouring to hide curve,</li>
	<li>Shadow: draw a little shadow down of your curve (it's useles but it looks good)</li>
	<li>SnapToBottom: fill the surface below the curve,</li>
</ul>

\image html linestate.png Different line states: open/closed, filled, snap to bottom, shadow, no contour, etc...
*/
class PGLCORE_EXT_CLASS CPGLLine : public CPGLObject
{
PGL_DECLARE_DYNCREATE(CPGLLine);
public:
	//! \name Enumerations
	//@{
	//! Interpolation types
	enum EInterpolationType
	{
		//! steps (zero order interpolation)
		InterpolationTypeStep,
		//! piece-wize linear interpolation
		InterpolationTypeLinear,
		//! Cardinal splines (uses tension parameter)
		InterpolationTypeSpline,
		//! multiple line strip
		InterpolationTypeSegment
	};

	//! Marker type (OBSOLETE see CPGLMarker)
	enum EMarkerType
	{
		//! No marker
		MarkerTypeNone = 0,
		//! Filled circle
		MarkerTypeCircle = 1,
		//! Circle (not filled)
		MarkerTypeContour = 2,
		//! Triangle
		MarkerTypeTriangle = 3,
		//! Box
		MarkerTypeSquare = 4
	};

	//@}
public:
	//! \name Constructors
	//@{
	//! default constructor
	CPGLLine(const CPGLColor& _FrontColor=CPGLColor(), const CPGLColor& _FillColor=CPGLColor(0.3f,0.3f,0.3f,1),
		EInterpolationType eInterpolationType = InterpolationTypeLinear,
		EMarkerType eMarkerType=MarkerTypeNone,LPCTSTR _szDashPattern=PGL_LINE_CONT);
	//! copy constructor
	CPGLLine(const CPGLLine& l):m_pMarker(CPGLMarkerPtr()){*this=l;};
	//! assignment constructor
	CPGLLine& operator = (const CPGLLine& l);
	//! destructor
	virtual ~CPGLLine();
	//! Cleans marker
	void CleanMarker();
	//@}

	//! \name GUI
	//@{
	//! adds context menu items...
	virtual void AddContextMenuItems(CMenu* pMenu);
	//! adds the line property page to the property sheet dialog.
	virtual void AddPropertyPage(CPropertySheet *pPropSheet);
	//@}

	//! \name Interpolation types
	//@{
	//! Convert EInterpolationType to String
	static CString InterpolationTypeToString(EInterpolationType eInterpolationType);
	//! Converts string to interpolation type
	static EInterpolationType StringToInterpolationType(LPCTSTR szInterpolationType);

	//! Sets the interpolation type
	void SetInterpolationType(EInterpolationType eInterpolationType)	{ m_eInterpolationType = eInterpolationType;};
	/*! \brief Spline tension

	Real number that specifies how tightly the curve bends through the coordinates of the cardinal spline. 
	Note that when the tension is 0, the points are connected by straight lines
	*/
	void SetTension( double dTension)					{	m_dTension = __max(0,dTension);};
	//! returns the interpolation type
	EInterpolationType GetInterpolationType() const		{ return m_eInterpolationType;};
	//! return spline tension
	double GetTension() const							{	return m_dTension;};
	//@}

	//! \name Markers
	//@{
	//! Sets the marker type (obsolete)
	void SetPointType(EMarkerType eMarkerType)	{	SetMarkerType(eMarkerType);};
	//! Sets the marker type (obsolete)
	void SetMarkerType(EMarkerType eMarkerType);


	//! Set the marker
	void SetMarker( CPGLMarkerPtr pMarker);
	//! return the marker, const
	const CPGLMarkerPtr GetMarker() const				{	return m_pMarker;};
	//! return the marker
	CPGLMarkerPtr GetMarker()							{	return m_pMarker;};
	//! Set marker and line color synchronized
	void SetMarkerColorSynchronized(bool yes)		{	m_bMarkerColorSynchro=yes;};
	//! return true if marker and line colors are synchronized (default behavior)
	bool IsMarkerColorSynchronized() const			{	return m_bMarkerColorSynchro;};
	//@}

	//! \name Properties setters and getters
	//@{
	//! returns the Line type 
	const CString& GetDashPattern() const			{ return m_sDashPattern;};
	//! returns the point width (obsolete, use MarkerWidth)
	float GetPointWidth() const						{ return GetMarkerWidth();};
	//! returns the point width (OBSOLETE)
	float GetMarkerWidth() const					{ if (m_pMarker) return (float)m_pMarker->GetRadius(); else return 0;};
	//! returns the line width 
	float GetLineWidth() const			{ return m_fLineWidth;};
	//! returns number of points in multiple line strip
	UINT GetStripSize() const {	return m_iStripSize;};
	//! Sets the strip size for multiple strip mode
	void SetStripSize(UINT size) {	m_iStripSize = __max(2, size);};


	/*! \brief Sets the line type

	The user can set custom patterns by entering a string containing the custom pattern.
	There are also predefined patterns.
	<ul>
		<li> #PGL_LINE_CONT : -------
		<li> #PGL_LINE_BARBAR : - - - -
		<li> #PGL_LINE_BARPOINT :-:-:-:
		<li> Any custom string pattern, for instance "4 10" will produce a pattern composed of 4 pixels of dark, 10 pixels of nothing,
	</ul>
	\sa GetDashPattern
	*/
	void SetDashPattern(LPCTSTR _sDashPattern)	{	m_sDashPattern = _sDashPattern;};
	//! sets the point width (in pixels), obsolete use SetMarkerWidth
	void SetPointWidth(float _fPointWidth)		{	SetMarkerWidth(_fPointWidth);}; 
	//! sets the point width (in pixels) (obsolete)
	void SetMarkerWidth(float _fMarkerWidth)	{	if (m_pMarker) m_pMarker->SetRadius(_fMarkerWidth);}; 
	//! sets the line width (in pixels)
	void SetLineWidth(float _fLineWidth)		{	m_fLineWidth=(float)__max(0.0,_fLineWidth);};
	//! Returns true if line is filled
	bool IsFilled() const						{	return m_bFilled;};
	//! Sets the filling bit
	void SetFilled(bool fill = true)			{	m_bFilled = fill;};
	//! Returns true if line is open	
	bool IsOpen() const							{	return m_bOpen;};
	//! Sets the open bit
	void SetOpen(bool open = true)				{	m_bOpen = open;};
	//! Returns true if line has contour	
	bool IsContoured() const					{	return m_bContour;};
	//! Set the contour bit
	void SetContoured(bool visible = true)		{	m_bContour = visible;};
	//! Returns true if the two vertical lines are appended to bottom of the plot	
	bool IsSnapBottom() const					{	return m_bSnapBottom;};
	//! Sets the snap bottom bit
	void SetSnapBottom(bool snap = true)		{	m_bSnapBottom = snap;};
	//! Returns true if a shadow is drawed	
	bool IsShadowing() const					{	return m_bShadow;};
	//! Set shadow bit
	void SetShadowing(bool on = true)			{	m_bShadow = on;};
	//@}

	//! \name Virtual plotting functions
	//@{
	//! Update the dash pattern
	void SetDashGfx(gfxinterface::CGfxInterface& gfx);
	//! Update the line state
	void SetLineState(gfxinterface::CGfxInterface& gfx);
	//! Returns the line type using gfxinterface
	DWORD GetELineType() const;
	//! Returns the rect type using gfxinterface
	DWORD GetERectType() const;
	//! Main plot function
	virtual void PlotGfx(gfxinterface::CGfxInterface& gfx);
	//! Legend plot function
	virtual void PlotLegendGfx(gfxinterface::CGfxInterface& gfx, const CPGLRectD& rBox);
	//@}

	//! \name Scripting methods
	//@{
	//! property enumeration
	enum ELineProp
	{
		LinePropUnknow,
		LinePropWidth,
		LinePropDash,
		LinePropMarker,
		LinePropOpen,
		LinePropContour,
		LinePropSnapBottom,
		LinePropFilled,
		LinePropShadow,
		LinePropInterpolation,
		LinePropStripSize,
		LinePropTension
	};
	PGL_DECLARE_SCRIPTING(Line);
	//@}

	//! \name Serialization and debugging
	//@{
	//! Serialization function
	void SerializeXML(CPGLArchive& ar);
	#ifdef _DEBUG
		//! MFC dump
	    virtual void Dump( CDumpContext& dc ) const;
		//! MFC AsserValid
	    virtual void AssertValid() const;   
	#endif
	//@}
	
protected:
	//! \name (Pseudo) Abstract functions (to be implement in inherited functions)
	//@{
	//! Plot the line
	virtual void PlotLineStripGfx(gfxinterface::CGfxInterface& gfx) {};
	//! Plot markers
	virtual void PlotPointStripGfx(gfxinterface::CGfxInterface& gfx){};
	//! Plot Start, end arrows
	virtual void PlotArrowsGfx(gfxinterface::CGfxInterface& gfx){};
	//@}

	void UpdateMarker();
	
	//! \name Attributes
	//@{
	//! interpolation type
	EInterpolationType m_eInterpolationType;
	//! spline tension
	double m_dTension;
	//! marker
	CPGLMarkerPtr m_pMarker;
	//! marker colors need updates
	bool m_bMarkerNeedUpdate;
	//! true if marker color and line are synchronized
	bool m_bMarkerColorSynchro;
	//! Line dashing type
	CString m_sDashPattern;
	//! Line width (pixels)
	float m_fLineWidth;
	//! Filled bit
	bool m_bFilled;
	//! Contour bit
	bool m_bContour;
	//! Open bit
	bool m_bOpen;
	//! Snap to bottom bit
	bool m_bSnapBottom;
	//! Shadow bit
	bool m_bShadow;
	//! Size of line strip
	UINT m_iStripSize;
	//@}  
};

PGL_DECLARE_SMARTPTR( CPGLLine );

#define PGL_INTERPOLATION_STEP		CPGLLine::InterpolationTypeStep
#define PGL_INTERPOLATION_LINEAR	CPGLLine::InterpolationTypeLinear
#define PGL_INTERPOLATION_SEGMENT	CPGLLine::InterpolationTypeSegment
#define PGL_POINT_NONE				CPGLLine::MarkerTypeNone
#define PGL_POINT_SIMPLE			CPGLLine::MarkerTypeCircle
#define PGL_POINT_CONTOUR			CPGLLine::MarkerTypeContour
#define PGL_POINT_TRIANGLE			CPGLLine::MarkerTypeTriangle
#define PGL_POINT_SQUARE			CPGLLine::MarkerTypeSquare

/*! \example linedash.cpp
 Different available dashing patterns:

\image html linedash.png "Line dashing"
*/
/*! \example linefcs.cpp
Closing, filling and other properties of lines.

\image html linefcs.png "Line closing and filling"
*/
/*! \example spline.cpp
Splines.

\image html spline.png "Spline and tension"
*/
/*! \example marker.cpp
Different available markers.

\image html marker.png "Different types of markers"
*/

#endif // !defined(AFX_LINEGL_H__4DACBB76_9EFC_11D4_8A95_D4B14EEC3D7F__INCLUDED_)
